#!/usr/bin/env ruby

require 'English'
require 'gserver'

require 'djb-netstrings'
require 'json_rpc'

class PeerCafeServer < GServer
  include DjbNetstrings
  include JSON_RPC

  BadRequestError = Class.new(StandardError)

  CURRENT_VERSION = 0.1
  PEER_CAFE_PORT = 8765
  SERVER_HOST = "127.0.0.1"
  MAX_CONNECTIONS = 5
  AUDIT = false
  DEBUG = false

  PEER_LIST_SIZE = 5

  def initialize
    @peer_addrs = []
    @peer_lock = Mutex.new
    @current_id = 0

    json_request_handler :get_peer_list

    super(PEER_CAFE_PORT, 
          SERVER_HOST, 
          MAX_CONNECTIONS, 
          $stderr, 
          AUDIT,
          DEBUG )

    puts "PeerCafe Server Started...\n"
  end

  MAX_MSG_SIZE = 256
  def serve(sock)
    ip_addr = sock.peeraddr[2] || sock.peeraddr[3]
    puts "#{ip_addr} connected..."

    begin
      # Pull the message out of the Netstring
      msg = DjbNetstrings.ns_read(sock, MAX_MSG_SIZE)
      puts "Got Message: " + msg
      response = json_handle_msg(msg)
      DjbNetstrings.ns_write(sock, response) if response
    rescue => e
      puts "ERROR: #{e}"
      puts "- - - - - - - - - - -"
      puts e.backtrace
      puts "- - - - - - - - - - -"
    ensure
      # Want the server to be lightweight so we only support one request
      # per connection, then close the socket.
      sock.close
    end

  end

  private

  def get_peer_list(params, id)
    (params.size == 2 and params.has_key?('ip') and 
     params.has_key?('port')) or raise BadRequestError 

     response = ""
     @peer_lock.synchronize do
       response = json_response(@peer_addrs, nil, id)
       @peer_addrs << params
       @peer_addrs.shift if @peer_addrs.size > PEER_LIST_SIZE
     end

     response
  end
end

server = PeerCafeServer.new
server.start
server.join

